 using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace GAscheduler
{
    class RulesDatabase
    {
        public ArrayList m_alRuleDatabase; // database of all the rules a schedule must follow
        private RulesParser m_rpParser = new RulesParser(); // a parser to create rules from a file

        /// <summary>
        /// Constructor. Takes in a file path, which it passes to the parser. The parser 
        ///     will then pass the path to the lexer, who passes it to the file reader 
        ///     to open and read the file. Once the file is read, the lexer produces a 
        ///     list of tokens which it hands back to the parser. The parser then creates 
        ///     a database of rule objects, which is assigned to this class' data member 
        ///     m_alRuleDatabase.
        /// </summary>
        /// <param name="sFilePath"></param>
        public RulesDatabase(string sFilePath)
        {
            m_rpParser.PreParse(sFilePath); // passes file path to the parser

            m_alRuleDatabase = m_rpParser.Parse(); // gets back a list of rule objects
        } // RulesDatabase

        /// <summary>
        /// Consult takes in a schedule and calls the CrosscheckRule function of each rule 
        ///     object in the database. Each of those functions returns a boolean value 
        ///     indicating whether or not the rule was met. Consult keeps a count of all
        ///     crosschecks' success and failure, then produces a percent accuracy based 
        ///     on the result. This floating point number is returned.
        /// </summary>
        /// <param name="sch"></param>
        /// <returns></returns>
        public float Consult(Schedule sch)
        {
            int iCorrect = 0;   // number of crosschecks that met the rules
            int iIncorrect = 0; // number of crosschecks that broke the rules
            float fPercent;     // percent accuracy of the schedule in following the rules

            foreach (RuleCode c in m_alRuleDatabase) // for every rule in the database...
            {
                if (c.CrosscheckRule(sch))           // see if it is met by the schedule
                    iCorrect++;                      // if so, note that
                else
                    iIncorrect++;                    // if not, note that as well
            }

            // calculate the percent accuracy of the schedule in following the rules
            fPercent = ((float)iCorrect) / ((float)(iCorrect + iIncorrect));

            fPercent = (fPercent + PeriodConflictCheck(sch) + RoomConflictCheck(sch)) / ((float)3);

            return fPercent; // return that percent
        } // Consult

        // TODO: recode to check for period conflict AMONG PERIODS, not courses
        private float PeriodConflictCheck(Schedule sch)
        {
            int iAccum = 0;

            for (int i = 0; i < sch.getLength(); i++)
            {
                for (int j = i; j < sch.getLength(); j++)
                {
                    if (sch.get(i).period == sch.get(j).period)
                    {
                        iAccum++;
                    }
                }
            }

            return ((float)iAccum) / ((float)sch.getLength());
        }

        private float RoomConflictCheck(Schedule sch)
        {
            int iAccum = 0;

            for (int i = 0; i < sch.getLength(); i++)
            {
                for (int j = i; j < sch.getLength(); j++)
                {
                    if (sch.get(i).room == sch.get(j).room)
                    {
                        iAccum++;
                    }
                }
            }

            return ((float)iAccum) / ((float)sch.getLength()); // TODO: invert to get correct percent
        }
    }
}
